﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ToracTechnologies.EntityFramework;
using ToracTechnologies.ExpressionTree.Testing.EntityFramework;
using ToracTechnologies.ExpressionTreeLibrary.DynamicApi;
using ToracTechnologies.ExpressionTreeLibrary.DynamicApi.Framework;
using ToracTechnologies.ExpressionTreeLibrary.ExtensionMethods.IQueryable;

namespace ToracTechnologies.ExpressionTree.Testing.DynamicApi
{

    [TestClass]
    public class EfDynamicUnitTest
    {

        #region Select

        [TestMethod]
        public void Select_Test1()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.Add10Rows(true);

                var sql = DP.Fetch<Ref_Test>(false);

                sql = sql.OrderByDescending("Id");

                //grab the field from the parameter builder
                var paramBuilderResults = ParameterBuilder.BuildParameterFromStringName<Ref_Test>("Id");

                var ids = sql.Select(ExpressionBuilder.Select<Ref_Test, int>(paramBuilderResults)).ToArray();

                for (int i = 0; i < ids.Length; i++)
                {
                    var x = 10 - i;
                    Assert.AreEqual(x, ids[i]);
                }
            }
        }

        [TestMethod]
        public void Select_Test2()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.Add10Rows(true);

                var sql = DP.Fetch<Ref_Test>(false);

                sql = sql.OrderByDescending("Id");

                //grab the field from the parameter builder
                var paramBuilderResults = ParameterBuilder.BuildParameterFromLinqPropertySelector<Ref_Test>(x => x.Id);

                var ids = sql.Select(ExpressionBuilder.Select<Ref_Test, int>(paramBuilderResults)).ToArray();

                for (int i = 0; i < ids.Length; i++)
                {
                    var x = 10 - i;
                    Assert.AreEqual(x, ids[i]);
                }
            }
        }

        #endregion

        #region Order By Descending

        [TestMethod]
        public void OrderByDescending_Test1()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.Add10Rows(true);

                var sql = DP.Fetch<Ref_Test>(false);

                sql = sql.OrderByDescending("Id");

                var records = sql.ToArray();

                for (int i = 0; i < records.Length; i++)
                {
                    var x = 10 - i;
                    Assert.AreEqual(x, records[i].Id);
                }
            }
        }

        [TestMethod]
        public void OrderByDescending_Test2()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                const int howMany = 5;

                EntityFrameworkUnitTest.AddRows(howMany, true);

                var sql = DP.Fetch<Ref_Test>(false);

                sql = sql.OrderByDescending("Description");

                var records = sql.ToArray();

                for (int i = 0; i < records.Length; i++)
                {
                    var x = howMany - i;
                    Assert.AreEqual("Test" + x, records[i].Description);
                }
            }
        }

        [TestMethod]
        public void OrderByAscending_Test1()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.Add10Rows(true);

                var sql = DP.Fetch<Ref_Test>(false);

                sql = sql.OrderBy("Id");

                var records = sql.ToArray();
                for (int i = 0; i < records.Length; i++)
                {
                    Assert.AreEqual(i + 1, records[i].Id);
                }
            }
        }

        [TestMethod]
        public void OrderByAscending_Test2()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.AddRows(5, true);

                var sql = DP.Fetch<Ref_Test>(false);

                sql = sql.OrderBy("Description");

                //we need to take 5 because when you get "Test_10" it messes up the alphabetical order

                var records = sql.ToArray();
                for (int i = 0; i < records.Length; i++)
                {
                    Assert.AreEqual("Test" + (i + 1), records[i].Description);
                }
            }
        }

        #endregion

        #region Pagination

        [TestMethod]
        public void Pagination_Test1()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.Add10Rows(true);

                var sql = DP.Fetch<Ref_Test>(false);

                const int howManyPerPage = 5;
                const int currentPage = 2;

                sql = sql.OrderBy("Id").PaginateResults(currentPage, howManyPerPage);

                var records = sql.ToArray();

                Assert.AreEqual(records.Count(), howManyPerPage);

                for (int i = 0; i < records.Length; i++)
                {
                    var x = (((currentPage - 1) * howManyPerPage) + i) + 1;
                    Assert.AreEqual(x, records[i].Id);
                }
            }
        }

        [TestMethod]
        public void Pagination_Test2()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.Add10Rows(true);

                var sql = DP.Fetch<Ref_Test>(false);

                const int howManyPerPage = 3;
                const int currentPage = 3;

                sql = sql.OrderBy("Id").PaginateResults(currentPage, howManyPerPage);

                var records = sql.ToArray();

                Assert.AreEqual(records.Count(), howManyPerPage);

                for (int i = 0; i < records.Length; i++)
                {
                    var x = (((currentPage - 1) * howManyPerPage) + i) + 1;
                    Assert.AreEqual(x, records[i].Id);
                }
            }
        }

        #endregion

        #region String And List Contains

        [TestMethod]
        public void StringContainsPropertyStringName_Test1()
        {
            EntityFrameworkUnitTest.TruncateTable();

            using (var DP = EntityFrameworkUnitTest.Create())
            {
                EntityFrameworkUnitTest.Add10Rows(true);

                var sql = DP.Fetch<Ref_Test>(false);

                var exp = EntityFrameworkUtilities.StringContains<Ref_Test>("Description", "Test");

                sql = sql.Where(exp);

                var records = sql.ToArray();

                Assert.AreEqual(10, records.Count());
            }
        }

        #endregion

    }

}
